/*
The surface-physics project: http://code.google.com/p/surface-physics/
Adds real world physics based on the Bullet physics engine, to bases in the Orbiter space
flight simulation software.

Written by Abhijit Nandy
License : Apache License 2.0

Bump_Heap.h
BulletBase management directly from within Bump. Objects of this class are created
in the Bump module and uses a BulletBase VESSEL as a proxy for inserting meshes and attaching
objects. The BulletBase has no other role other than key forwarding (as of now) which is
difficult to do from a module. This class merges Orbiter and Bullet functionality towards
achieving the above outlined purpose.

This is possible due to the extensive public API of VESSEL & its derived classes.

This file declares the interface for the Bump_Heap class. Its role:
1. Creates the BulletBase proxy VESSEL at the location of the passed base
2. Reads the base specific physics file and staggers creation of objects in update()
   which is called at every sim step.
3. Reads command from a BulletBase public member and passes it on to components/attachments or
	processes them itself as reqd.
4. Scans the sky for nearby objects and attaches/detaches them as needed(does not scan in every step)



*/


#pragma once

#include "orbitersdk.h"
#include "BulletBase.h"



#include "btBulletDynamicsCommon.h"

#define MAX_OBJECTS 10
#define MAX_STRLEN 50

//Useful macros
#define V3ARGS(a)	(a).x, (a).y, (a).z

class Bump_BaseObject;


/**
 * Based on last action, a FSM based on Orbiter's time step
 * Used for gradual loading of objects into the simulation
 */
enum BaseMode
{
	IDLE,
	CREATED_BB,
	OPENED_FILE,	//loading of objects in this state till end of physics file
	PARSED_FILE		//Normal running mode after all objects loaded
};


/**
 * The Bump_Heap to create and manage a BulletBase
 */
class Bump_Heap
{
#pragma message("Bump_Heap.h included")

	//Physics stuff, dynamics world maintained by Bump
	btDynamicsWorld* m_dynamicsWorld;

	//General Physics world variables
	btAlignedObjectArray<btCollisionShape*> *m_collisionShapes;

	//Offset of this base in physics world
	btVector3 physicsWorldOffset;


	//Handle to base, reference body OBJECT
	OBJHANDLE hObjBase, hObjRefBody;


	VECTOR3 gposBase;

	//Section cutoff point : should there be section specific cutoffs read from file ?
	double cutoff;



	/* Attachment handles for this base(all managed objects could be attachments)
	 * These are just handles and the actual attachment needs to be created
	 * dynamically and the handle put here.
	 *
	 * This is not required, why duplicate info which can be got from Orbiter anytime ?
	 */
	//int num_attachments;
	//ATTACHMENTHANDLE atBase[MAX_OBJECTS];

	//Physics file
	FILEHANDLE physicsFile;

	//Objects managed by this base
	int numObjects;
	Bump_BaseObject *bbObj[MAX_OBJECTS];

	//WIP, template based object creation
	template<class T>
	void createTypedBaseObject();

	//Switch-case based object creation
	void createBaseObject(char *strType, char *strObjName, char *line);

	//The private base data is needed by these classes
	//TODO: This is not a great idea!, any future subclasses of the below
	//classes will have to be added here as friendship isnt inherited, find a better way!
	//Templated object creation or preprocessing maybe a solution
	friend class Bump_ATV;


	//Component friends
	friend class Bump_ExternalStaticGeometry;
	friend class Bump_Ball;
	friend class Bump_Plate;


public:

	//Base Name
	char strBaseName[MAX_STRLEN];

	//Latitude, longitude, radius of parent planet, global position
	double lng, lat, rad;

	//Pointers to associated BulletBase, to read commands from it
	OBJHANDLE hObjBulletBase;
	VESSEL3 *vBulletBase;
	BulletBase *bb;

	//Used to track loads of objects
	BaseMode mode;

	static const int BULLET_WORLD_SIZE = 10000;


	Bump_Heap();
	virtual ~Bump_Heap();

	//Main base management functions
	void	init(OBJHANDLE hObj, OBJHANDLE hObjRBody);
	void	prestep(double SimT, double SimDT, double MJD);
	void	poststep(double SimT, double SimDT, double MJD);
	void 	exit();

	//Physics file reading utilities
	void	readPhysicsFileDescription(void);
	void	readCreatePhysicsFileObject(void);

	//Physics rigid body creation
	btRigidBody*
	localCreateRigidBody(float mass, const btTransform& startTransform,btCollisionShape* shape);

	//Section update
	void refreshSections(void);


	void 	setDynamicsWorld(btDynamicsWorld* dynamicsWorld)
	{ m_dynamicsWorld = dynamicsWorld; }

	void 	setCollisionShapesArray(btAlignedObjectArray<btCollisionShape*> *collisionShapes)
	{ m_collisionShapes = collisionShapes; }
};
